﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Collections;

namespace UtilidadesDom
{
    public class StringUtil
    {
        /// <summary>
        /// Genera una cadena de la forma Propiedad=Valor[, Propiedad=Valor] para almanenar datos en la descripción de un log, 
        /// a partir de una instancia de un objeto, evalúa toda la profundidad del objeto
        /// Soporta objetos que pueden contener propiedades de tipos básicos (int, double, bool), tipos nulleables (int?, bool?, DateTime?), string, DateTime (que formatea usnado 
        /// IUUtil) o objetos o arreglos de los mismos.
        /// </summary>
        /// <param name="objeto"></param>
        /// <returns></returns>
        public static string generarCadenaParaLogsDeObjeto(object objeto)
        {
            string cadena = "";
            if (objeto == null)
                return "null";
            try
            {
                var array = (object[])objeto;
                var c = "";
                foreach (var item in array)
                {
                    c += agregarACadenaDescripcionLog(c,
                         generarCadenaParaLogsDeObjeto(item));
                }
                return "[ " + c + " ]";
            }
            catch (InvalidCastException)
            {
                if (objeto.GetType().GetProperties().Length == 0)
                    return objeto.ToString();
                else if (objeto.GetType().Equals(typeof(string)))
                    return "\"" + objeto.ToString() + "\"";
                else if (objeto.GetType().Equals(typeof(DateTime)))
                    return ((DateTime)objeto).ToString();
                else if (objeto.GetType().GetInterfaces().Contains(typeof(IEnumerable)))
                {
                    var c = "";
                    foreach (var item in (IEnumerable)objeto)
                    {
                        c += agregarACadenaDescripcionLog(c,
                                generarCadenaParaLogsDeObjeto(item));
                    }
                    return "[ " + c + " ]";
                }
                try
                {
                    var rt = (System.Data.Metadata.Edm.RelationshipType)objeto;
                    return "";
                }
                catch (InvalidCastException)
                {
                    try
                    {
                        var re = (System.Data.Objects.DataClasses.RelatedEnd)objeto;
                        return "";
                    }
                    catch (InvalidCastException)
                    {
                        foreach (PropertyInfo propiedad in objeto.GetType().GetProperties())
                        {
                            if (propiedad.CanRead)
                            {
                                cadena += agregarACadenaDescripcionLog(cadena, propiedad.Name,
                                     generarCadenaParaLogsDeObjeto(propiedad.GetValue(objeto, null)));
                            }
                        }
                    }
                }
            }
            return "{ " + cadena + " }";
        }

        private static string agregarACadenaDescripcionLog(string cadena, string propiedad, string valor)
        {
            var s = "";
            if (cadena.Equals(""))
                s += propiedad + " = " + valor;
            else
                s += ", " + propiedad + " = " + valor;
            return s;
        }

        private static string agregarACadenaDescripcionLog(string cadena, string valor)
        {
            var s = "";
            if (cadena.Equals(""))
                s += valor;
            else
                s += ", " + valor;
            return s;
        }
    }
}
